
#include <stdlib.h>
#include <string.h>

#include "tme_file_fmt.h"
#include "tme_mmap.h"
#include "tme_utils.h"
#include "tme_log.h"

/* -------------------- file api -------------------- */

/* 文件大小的变化都经由mmap,可在此截取文件大小变化信息 */
void* _tme_mmap_create(TME_File* fp, int32_t size, int32_t addr)
{
    void* result = tme_mmap_create(fp->fp, size, addr, fp->isReadOnly);
    if (result && !fp->isReadOnly && fp->head)
    {
        /* 更新文件大小信息 */
        int32_t fileSize = ftell(fp->fp);
        if (fileSize > fp->head->fileSize) {
            fp->head->fileSize = fileSize;
        }
    }
    return result;
}

/* 根据fat单元序号,获得文件实际地址 */
static inline int32_t _tme_fatIndex2FileAddr(TME_Head* head, int32_t fatIndex)
{
    /* 排列规律: [2K,文件头]+[2k,FAT表]+[1M,数据]+[2k,FAT表]+[1M,数据]... */
    
    /* 所属第几个fat表 */
    int32_t count = fatIndex / head->fatUnitNumber;
    /* fat表后紧跟的内存块序号 */
    int32_t remain = fatIndex % head->fatUnitNumber;
    /* 每个fat表能映射的内存块总大小 */
    int32_t blockFullSize = head->fatUnitNumber * head->fatUnitBlockSize;
    /* 文件头 + (FAT + blockFull)*N + FAT + block */
    return head->headSize + (head->fatSize + blockFullSize) * count + head->fatSize + remain * head->fatUnitBlockSize;
}

/* 根据fat表个数,获得fat表在文件实际地址 */
static inline int32_t _tme_fatNumber2FileAddr(TME_Head* head, int32_t fatNumber)
{
    /* 每个fat表能映射的内存块总大小 */
    int32_t blockFullSize = head->fatUnitNumber * head->fatUnitBlockSize;
    /* 文件头 + (FAT + blockFull)*N */
    return head->headSize + (head->fatSize + blockFullSize) * fatNumber;
}

/* 基于一个fat链表节点,计算直到链表结束总共大小 */
static int32_t _tme_fat_chain_size(TME_File* fp, int32_t fatIndex)
{
    /* fat单元占用个数统计 */
    int32_t fatUnitUse = 0;
    /* 所在fat表 */
    int32_t index1 = fatIndex / fp->head->fatUnitNumber;
    /* fat表中的序号 */
    int32_t index2 = fatIndex % fp->head->fatUnitNumber;
    /* 遍历fat表 */
    while (index1 < fp->head->fatCount && index2 < fp->head->fatUnitNumber)
    {
        /* 链表结束,返回大小 */
        if (GET_FAT_UNIT_END(fp->fat[index1][index2]))
        {
            /* 单元个数 * 单元映射块大小 + 剩余大小 */
            return fatUnitUse * fp->head->fatUnitBlockSize + GET_FAT_UNIT_VALUE(fp->fat[index1][index2]);
        }
        /* 否则跳转到下一个位置 */
        else
        {
            fatUnitUse += 1;
            fatIndex = GET_FAT_UNIT_VALUE(fp->fat[index1][index2]);
            index1 = fatIndex / fp->head->fatUnitNumber;
            index2 = fatIndex % fp->head->fatUnitNumber;
        }
    }
    return -1;
}

/* 检查和尝试修复文件头,成功返回0 */
static int32_t _tme_headCheck(
    TME_Head* head,
    int32_t isExtend,
    int32_t isReadOnly,
    uint32_t* beginTickMs,
    uint32_t* diffTickMs)
{
    int32_t result = 0;
    /* 魔数检查 */
    if (head->magicNumber != *((uint32_t*)TME_MAGIC_NUMBER))
    {
        if (isReadOnly || isExtend) {
            TME_ERR("magic number hex(%02X %02X %02X %02X) error, ask \"%s\"",
                head->magicNumber & 0xFF,
                (head->magicNumber >> 8) & 0xFF,
                (head->magicNumber >> 16) & 0xFF,
                (head->magicNumber >> 24) & 0xFF,
                TME_MAGIC_NUMBER);
            result -= 1;
        }
        else {
            head->magicNumber = *((uint32_t*)TME_MAGIC_NUMBER);
        }
    }
    /* 版本号为空 */
    if (head->version == 0) {
        if (isReadOnly || isExtend) {
            TME_ERR("version can not be zero"); 
            // result -= 1; /* 只做警告,不强制要求 */
        }
        else {
            head->version = TME_VERSION;
        }
    }
    /* 文件大小 */
    ;
    /* 必要参数检查 */
    if (head->headSize != TME_HEAD_SIZE) {
        if (isReadOnly || isExtend) {
            TME_ERR("headSize %d error, ask %d", head->headSize, TME_HEAD_SIZE); 
            result -= 1;
        }
        else {
            head->headSize = TME_HEAD_SIZE;
        }
    }
    if (head->fatSize != FAT_SIZE) {
        if (isReadOnly || isExtend) {
            TME_ERR("fatSize %d error, ask %d", head->fatSize, FAT_SIZE); 
            result -= 1;
        }
        else {
            head->fatSize = FAT_SIZE;
        }
    }
    if (head->fatUnitNumber != FAT_UNIT_NUMBER) {
        if (isReadOnly || isExtend) {
            TME_ERR("fatUnitNumber %d error, ask %d", head->fatUnitNumber, FAT_UNIT_NUMBER); 
            result -= 1;
        }
        else {
            head->fatUnitNumber = FAT_UNIT_NUMBER;
        }
    }
    if (head->fatUnitBlockSize != FAT_UNIT_BLOCK_SIZE) {
        if (isReadOnly || isExtend) {
            TME_ERR("fatUnitBlockSize %d error, ask %d", head->fatUnitBlockSize, FAT_UNIT_BLOCK_SIZE); 
            result -= 1;
        }
        else {
            head->fatUnitBlockSize = FAT_UNIT_BLOCK_SIZE;
        }
    }
    if (head->attrFatIndex != ATTR_TAB_FAT_INDEX) {
        if (isReadOnly || isExtend) {
            TME_ERR("attrFatIndex %d error, ask %d", head->attrFatIndex, ATTR_TAB_FAT_INDEX); 
            result -= 1;
        }
        else {
            head->attrFatIndex = ATTR_TAB_FAT_INDEX;
        }
    }
    if (head->attrUnitSize != ATTR_TAB_UNIT_SIZE) {
        if (isReadOnly || isExtend) {
            TME_ERR("attrUnitSize %d error, ask %d", head->attrUnitSize, ATTR_TAB_UNIT_SIZE); 
            result -= 1;
        }
        else {
            head->attrUnitSize = ATTR_TAB_UNIT_SIZE;
        }
    }
    if (head->attrIdleId == 0) {
        if (isReadOnly || isExtend) {
            TME_ERR("attrIdleId %d error, ask != 0", head->attrIdleId); 
            result -= 1;
        }
        else {
            head->attrIdleId = 1;
        }
    }
    if (head->timeFatIndex != TIME_TAB_FAT_INDEX) {
        if (isReadOnly || isExtend) {
            TME_ERR("timeFatIndex %d error, ask %d", head->timeFatIndex, TIME_TAB_FAT_INDEX); 
            result -= 1;
        }
        else {
            head->timeFatIndex = TIME_TAB_FAT_INDEX;
        }
    }
    if (head->attrNameFatIndex != ATTR_NAME_TAB_FAT_INDEX) {
        if (isReadOnly || isExtend) {
            TME_ERR("attrNameFatIndex %d error, ask %d", head->attrNameFatIndex, ATTR_NAME_TAB_FAT_INDEX); 
            result -= 1;
        }
        else {
            head->attrNameFatIndex = ATTR_NAME_TAB_FAT_INDEX;
        }
    }
    /* 文件时间 */
    uint16_t year = 0;
    uint8_t month = 0;
    uint8_t day = 0;
    uint32_t sec = 0;
    uint32_t ms = 0;
    uint32_t tickMs = 0;
    tme_utils_getTime(&year, &month, &day, &sec);
    tickMs = tme_utils_getTickMs();
    ms = sec * 1000 + tickMs % 1000;
    /* 不能出现大于当前时间的情况 */
    if (isReadOnly || isExtend)
    {
        /* 毫秒值不得超过1天的量 */
        if (head->beginMs >= 24 * 3600 * 1000)
        {
            TME_ERR("beginMs %d error, ask less than 86400000(1 day)", head->beginMs); 
            result -= 1;
        }
        /* 生成两个字符串进行比较 */
        else
        {
            char strFile[32] = {0};
            char strCurr[32] = {0};
            snprintf(strFile, sizeof(strFile), "%05d.%03d.%03d.%02d.%02d.%02d.%03d",
                head->beginYear, head->beginMonth, head->beginDay,
                head->beginMs/1000/60/60, head->beginMs/1000/60%60, head->beginMs/1000%60, head->beginMs%1000);
            snprintf(strCurr, sizeof(strCurr), "%05d.%03d.%03d.%02d.%02d.%02d.%03d",
                year, month, day, ms/1000/60/60, ms/1000/60%60, ms/1000%60, ms%1000);
            if (strcmp(strFile, strCurr) > 0)
            {
                TME_ERR("file fime error, %s(file) > %s(current)", strFile, strCurr); 
                result -= 1;
            }
            /* 对于续写,仅支持当天内的文件 */
            if (isExtend && (
                head->beginYear != year ||
                head->beginMonth != month ||
                head->beginDay != day))
            {
                TME_ERR("extend mode ask same day, %s(file) %s(current)", strFile, strCurr); 
                result -= 1;
            }
        }
    }
    /* 生成文件时间 */
    else
    {
        head->beginYear = year;
        head->beginMonth = month;
        head->beginDay = day;
        head->beginMs = ms;
    }
    if (beginTickMs) {
        *beginTickMs = tickMs;
    }
    if (diffTickMs) {
        *diffTickMs = ms - head->beginMs;
    }
    return result;
}

/* 拓展fat表 */
static int32_t _tme_file_fat_extend(TME_File* fp, int32_t fatCount)
{
    int32_t result = -1;
    do
    {
        /* 内存增长 */
        if (fatCount > fp->head->fatCount || !fp->fat)
        {
            /* isReadOnly模式下不许修改head */
            if (fatCount < fp->head->fatCount || fp->isReadOnly) {
                fatCount = fp->head->fatCount;
            }
            /* 分配内存 */
            if (!fp->fat) {
                fp->fat = (uint32_t**)calloc(1, sizeof(uint32_t*) * fatCount);
            }
            else {
                fp->fat = (uint32_t**)realloc(fp->fat, sizeof(uint32_t*) * fatCount);
            }
            if (!fp->fat) {
                TME_ERR("re/calloc(%p, size:%d) failed", fp->fat, sizeof(uint32_t*) * fatCount);
                break;
            }
            /* realloc不会清空新内存,手动清空 */
            for (int32_t i = fp->head->fatCount; i < fatCount; i++) {
                fp->fat[i] = NULL;
            }
            /* 更新长度信息 */
            if (!fp->isReadOnly) {
                fp->head->fatCount = fatCount;
            }
        }
        
        /* 从文件映射 */
        int32_t fatIndex = 0;
        for (; fatIndex < fp->head->fatCount; fatIndex++)
        {
            /* 映射 */
            if (!fp->fat[fatIndex])
            {
                fp->fat[fatIndex] = (uint32_t*)_tme_mmap_create(
                    fp, fp->head->fatSize, _tme_fatNumber2FileAddr(fp->head, fatIndex));
            }
            if (!fp->fat[fatIndex]) {
                // TME_ERR("mmap fat[%d] failed", fatIndex);
                break;
            }
        }
        if (fatIndex != fp->head->fatCount) {
            TME_ERR("mmap fat[%d] failed, isReadOnly:%d isExtend:%d", fatIndex, fp->isReadOnly, fp->isExtend);
            break;
        }

        result = 0;
    } while(0);
    return result;
}

void tme_file_close(TME_File* fp)
{
    if (!fp) {
        return;
    }
    /* 释放fat表映射内存 */
    if (fp->fat)
    {
        for (uint32_t i = 0; i < fp->head->fatCount; i++)
        {
            if (fp->fat[i])
            {
                tme_mmap_release((void*)fp->fat[i]);
                fp->fat[i] = NULL;
            }
        }
        free(fp->fat);
        fp->fat = NULL;
    }
    /* 释放head映射内存 */
    if (fp->head)
    {
        tme_mmap_release(fp->head);
        fp->head = NULL;
    }
    /* 释放文件 */
    if (fp->fp) {
        fclose(fp->fp);
        fp->fp = NULL;
    }
    free(fp);
}

TME_File* tme_file_open(const char* file, char mode)
{
    TME_File* fp = (TME_File*)calloc(1, sizeof(TME_File));
    int32_t result = -1;
    do
    {
        if (!fp) {
            TME_ERR("calloc size:%d failed", sizeof(TME_File));
            break;
        }
        /* 打开文件 */
        if (mode == 'r')
        {
            fp->isReadOnly = 1;
            fp->fp = fopen(file, "rb+");
        }
        else if (mode == 'w')
        {
            fp->fp = fopen(file, "rb+");
            if (!fp->fp) {
                fp->fp = fopen(file, "wb+");
            }
            else {
                fp->isExtend = 1; /* 这是续写模式 */
            }
        }
        else if (mode == 'c')
        {
            fp->fp = fopen(file, "wb+");
        }
        else {
            TME_ERR("unknown mode '%c', choose one from 'r'/'w'/'c'", mode);
            break;
        }
        if (!fp->fp) {
            TME_ERR("open mode:'%c' %s failed", mode, file);
            break;
        }
        /* 映射文件头内存 */
        fp->head = (TME_Head*)_tme_mmap_create(fp, TME_HEAD_SIZE, 0);
        if (!fp->head) {
            TME_ERR("mmap head failed: file:%s", file);
            break;
        }
        /* 检查&填写文件头 */
        result = _tme_headCheck(fp->head, fp->isExtend, fp->isReadOnly, &fp->beginTickMs, &fp->diffTickMs);
        if (result != 0)
        {
            TME_ERR("headCheck failed(%d): file:%s", result, file);
            break;
        }
        /* fat表个数为0,创建第一个fat表,如果不是只读的话 */
        if (fp->head->fatCount == 0)
        {
            if (fp->isReadOnly) {
                TME_ERR("it's an empty file, fatCount:%d", fp->head->fatCount);
                break;
            }
            fp->head->fatCount = 1;
        }
        /* 映射所有fat表到内存 */
        result = _tme_file_fat_extend(fp, fp->head->fatCount);
        if (result != 0) {
            break;
        }
        /* 检查 || 创建全局唯一的 属性表 */
        int32_t index1 = fp->head->attrFatIndex / fp->head->fatUnitNumber;
        int32_t index2 = fp->head->attrFatIndex % fp->head->fatUnitNumber;
        if (GET_FAT_UNIT_TYPE(fp->fat[index1][index2]) != TME_FAT_UNIT_TYPE_ATTR)
        {
            if (!fp->isReadOnly && fp->fat[index1][index2] == 0)
            {
                TME_FatChain* fc = tme_fat_chain_open(fp, fp->head->attrFatIndex, TME_FAT_UNIT_TYPE_ATTR);
                if (fc)
                {
                    tme_fat_chain_close(fc);
                    /* 重置属性个数 */
                    fp->head->attrIdleId = 1;
                    fp->head->attrCount = 0;
                }
                else {
                    TME_ERR("create system attr tab failed, fatIndex:%d", fp->head->attrFatIndex);
                    break;
                }
            }
            else
            {
                TME_ERR("attr tab error, fatIndex:%d value:0x%X", fp->head->attrFatIndex, fp->fat[index1][index2]);
                break;
            }
        }
        /* 检查 || 创建全局唯一的 总览时间表 */
        index1 = fp->head->timeFatIndex / fp->head->fatUnitNumber;
        index2 = fp->head->timeFatIndex % fp->head->fatUnitNumber;
        if (GET_FAT_UNIT_TYPE(fp->fat[index1][index2]) != TME_FAT_UNIT_TYPE_TIME)
        {
            if (!fp->isReadOnly && fp->fat[index1][index2] == 0)
            {
                TME_FatChain* fc = tme_fat_chain_open(fp, fp->head->timeFatIndex, TME_FAT_UNIT_TYPE_TIME);
                if (fc) {
                    tme_fat_chain_close(fc);
                }
                else {
                    TME_ERR("create system time tab failed, fatIndex:%d", fp->head->timeFatIndex);
                    break;
                }
            }
            else {
                TME_ERR("time tab error, fatIndex:%d value:0x%X", fp->head->timeFatIndex, fp->fat[index1][index2]);
                break;
            }
        }
        /* 检查 || 创建全局唯一的 属性名称表 */
        index1 = fp->head->attrNameFatIndex / fp->head->fatUnitNumber;
        index2 = fp->head->attrNameFatIndex % fp->head->fatUnitNumber;
        if (GET_FAT_UNIT_TYPE(fp->fat[index1][index2]) != TME_FAT_UNIT_TYPE_ATTR_NAME)
        {
            if (!fp->isReadOnly && fp->fat[index1][index2] == 0)
            {
                TME_FatChain* fc = tme_fat_chain_open(fp, fp->head->attrNameFatIndex, TME_FAT_UNIT_TYPE_ATTR_NAME);
                if (fc) {
                    tme_fat_chain_close(fc);
                }
                else {
                    TME_ERR("create attr name tab failed, fatIndex:%d", fp->head->attrNameFatIndex);
                    break;
                }
            }
            else {
                TME_ERR("attr name tab error, fatIndex:%d value:0x%X", fp->head->attrNameFatIndex, fp->fat[index1][index2]);
                break;
            }
        }

        result = 0;
    } while(0);
    
    if (result != 0) {
        tme_file_close(fp);
        fp = NULL;
    }
    return fp;
}

/* -------------------- util api -------------------- */

uint32_t tme_file_getDiffMs(TME_File* fp)
{
    return tme_utils_getTickMs() - fp->beginTickMs + fp->diffTickMs;
}

/* -------------------- fat api -------------------- */

/* 基于fat链表头,根据数据地址定位fat单元序号,成功返回fat单元序号,失败-1 */
static int32_t _tme_fat_chain_seek(TME_File* fp, int32_t fatIndex, int32_t _offset, int32_t* blockOffset)
{
    /* 统计当前已位移量 */
    int32_t offset = 0;
    /* 所在fat表 */
    int32_t index1 = fatIndex / fp->head->fatUnitNumber;
    /* fat表中的序号 */
    int32_t index2 = fatIndex % fp->head->fatUnitNumber;
    /* 遍历fat表 */
    while (index1 < fp->head->fatCount && index2 < fp->head->fatUnitNumber)
    {
        /* 已经到达链表结尾 */
        if (GET_FAT_UNIT_END(fp->fat[index1][index2]))
        {
            if (blockOffset)
            {
                *blockOffset = _offset >= 0 ? (_offset - offset) : GET_FAT_UNIT_VALUE(fp->fat[index1][index2]);
                if (*blockOffset > GET_FAT_UNIT_VALUE(fp->fat[index1][index2])) {
                    *blockOffset = GET_FAT_UNIT_VALUE(fp->fat[index1][index2]);
                }
            }
            return index1 * fp->head->fatUnitNumber + index2;
        }
        /* 当前fat单元的内存范围能包含_offset */
        else if (offset <= _offset && _offset < offset + fp->head->fatUnitBlockSize)
        {
            if (blockOffset) {
                *blockOffset = _offset - offset;
            }
            return index1 * fp->head->fatUnitNumber + index2;
        }
        /* 否则跳转到下一个位置 */
        else
        {
            offset += fp->head->fatUnitBlockSize;
            fatIndex = GET_FAT_UNIT_VALUE(fp->fat[index1][index2]);
            index1 = fatIndex / fp->head->fatUnitNumber;
            index2 = fatIndex % fp->head->fatUnitNumber;
        }
    }
    return -1;
}

static TME_FatChain* _tme_fat_chain_open(TME_File* fp, int32_t fatIndex, TME_FAT_UNIT_TYPE type, TME_FatChain* _fc)
{
    TME_FatChain* fc = _fc;
    do
    {
        if (fatIndex < 0) {
            fatIndex = fp->head->fatIdleIndex;
        }
        /* fatIndex必须在最新一块序号范围内 */
        if (fatIndex > fp->head->fatIdleIndex) {
            TME_ERR("fatIndex out of range, ask %d(fatIndex) <= %d(fatIdleIndex)", fatIndex, fp->head->fatIdleIndex);
            break;
        }
        /* 超出已映射fat表范围 */
        if (fatIndex >= fp->head->fatCount * fp->head->fatUnitNumber)
        {
            /* 拓展fat表 */
            if (!fp->isReadOnly && (fatIndex < (fp->head->fatCount + 1) * fp->head->fatUnitNumber))
            {
                if (_tme_file_fat_extend(fp, fp->head->fatCount + 1) != 0) {
                    TME_ERR("_tme_file_fat_extend failed, fatCount:%d + 1", fp->head->fatCount);
                    break;
                }
            }
            else
            {
                TME_ERR("fatIndex out of range, ask %d(fatIndex) < %d(fat max)", fatIndex, fp->head->fatCount * fp->head->fatUnitNumber);
                break;
            }
        }

        if (!fc)
        {
            fc = (TME_FatChain*)calloc(1, sizeof(TME_FatChain));
            if (!fc) {
                TME_ERR("calloc size:%d failed", sizeof(TME_FatChain));
                break;
            }
        }

        /* 二维数组位置 */
        int32_t index1 = fatIndex / fp->head->fatUnitNumber;
        int32_t index2 = fatIndex % fp->head->fatUnitNumber;

        /* 这是新建 */
        if (fp->fat[index1][index2] == 0 || 
            (fatIndex == fp->head->fatIdleIndex && !fp->isReadOnly))
        {
            /* 更新fat单元空闲位置 */
            if (fatIndex >= fp->head->fatIdleIndex) {
                fp->head->fatIdleIndex = fatIndex + 1;
            }
            /* 初始化参数 */
            fc->type = type;
            if (!_fc)
            {
                fc->totalSize = 0;
                fc->writeSeek = 0;
                fc->readSeek = 0;
                fc->fatBeginIndex = fatIndex;
                fc->fatReadIndex = fatIndex;
            }
            fc->fatWriteIndex = fatIndex;
            fc->writeBlockOffset = 0;
            fc->readBlockOffset = 0;
            fc->fp = fp;
            /* 初始化fat单元 */
            if (fc->totalSize == 0) {
                SET_FAT_UNIT_BEGIN(fp->fat[index1][index2]);
            }
            SET_FAT_UNIT_END(fp->fat[index1][index2]); /* 在跳转下一块之前,默认当前块结束 */
            SET_FAT_UNIT_TYPE(fp->fat[index1][index2], type);
            SET_FAT_UNIT_VALUE(fp->fat[index1][index2], 0);
        }
        /* 这是打开现有 */
        else
        {
            /* 初始化参数 */
            fc->type = GET_FAT_UNIT_TYPE(fp->fat[index1][index2]);
            if (!_fc)
            {
                fc->totalSize = _tme_fat_chain_size(fp, fatIndex);
                fc->writeSeek = 0;
                fc->readSeek = 0;
                fc->fatBeginIndex = fatIndex;
                fc->fatWriteIndex = fatIndex;
            }
            fc->fatReadIndex = fatIndex;
            fc->writeBlockOffset = 0;
            fc->readBlockOffset = 0;
            fc->fp = fp;
        }

        /* 这是首次打开 */
        if (!_fc)
        {
            /* 把读指针移动到最前面,同时映射内存 */
            if (tme_fat_chain_readSeek(fc, 0) != 0)
            {
                TME_ERR("tme_fat_chain_readSeek failed, offset:0");
                tme_fat_chain_close(fc);
                fc = NULL;
                break;
            }
            /* 把写指针移动到最后,同时映射内存 */
            if (!fp->isReadOnly && tme_fat_chain_writeSeek(fc, -1) != 0)
            {
                TME_ERR("tme_fat_chain_readSeek failed, offset:0");
                tme_fat_chain_close(fc);
                fc = NULL;
                break;
            }
        }
        /* 这是写模式新开一块内存 */
        else if (!fp->isReadOnly)
        {
            void* newMem = _tme_mmap_create(
                fp, fp->head->fatUnitBlockSize, _tme_fatIndex2FileAddr(fp->head, fatIndex));
            /* 重新映射文件 */
            if (fc->writeBlock) {
                tme_mmap_release(fc->writeBlock);
            }
            fc->writeBlock = (uint8_t*)newMem;
        }
    } while(0);
    return fc;
}

TME_FatChain* tme_fat_chain_open(TME_File* fp, int32_t fatIndex, TME_FAT_UNIT_TYPE type)
{
    return _tme_fat_chain_open(fp, fatIndex, type, NULL);
}

void tme_fat_chain_close(TME_FatChain* fc)
{
    if (!fc || !fc->fp) {
        return;
    }
    /* 释放内存块 */
    if (fc->writeBlock) {
        tme_mmap_release(fc->writeBlock);
        fc->writeBlock = NULL;
    }
    if (fc->readBlock) {
        tme_mmap_release(fc->readBlock);
        fc->readBlock = NULL;
    }
    fc->fp = NULL;
}

int32_t tme_fat_chain_write(TME_FatChain* fc, const uint8_t* data, int32_t dataSize)
{
    if (!fc->fp || fc->fp->isReadOnly || !fc->writeBlock) {
        return -1;
    }
    /* 二维数组位置 */
    int32_t index1 = fc->fatWriteIndex / fc->fp->head->fatUnitNumber;
    int32_t index2 = fc->fatWriteIndex % fc->fp->head->fatUnitNumber;
    /* 总的写入数据量 & 局部数据量计数 */
    int32_t wCount = 0;
    int32_t wCountPart = 0;
    while (dataSize > 0)
    {
        /* 当前映射的内存块还有空间可写*/
        if (fc->writeBlockOffset < fc->fp->head->fatUnitBlockSize)
        {
            /* 将写入的数据量 */
            wCountPart = fc->fp->head->fatUnitBlockSize - fc->writeBlockOffset;
            if (wCountPart > dataSize) {
                wCountPart = dataSize;
            }
            /* 写数据 */
            memcpy(&fc->writeBlock[fc->writeBlockOffset], &data[wCount], wCountPart);
            /* 计数移动 */
            fc->writeSeek += wCountPart;
            fc->writeBlockOffset += wCountPart;
            wCount += wCountPart;
            dataSize -= wCountPart;
            /* 更新fat值(如果是在追加数据) */
            if (fc->writeSeek >= fc->totalSize)
            {
                fc->totalSize = fc->writeSeek;
                SET_FAT_UNIT_VALUE(fc->fp->fat[index1][index2], fc->writeBlockOffset);
            }
        }
        /* 当前块已满,寻找下一块 */
        else
        {
            /* 在追加数据,开辟新块 */
            if (fc->totalSize == fc->writeSeek)
            {
                _tme_fat_chain_open(fc->fp, fc->fp->head->fatIdleIndex, fc->type, fc);
                if (!fc->writeBlock) {
                    break;
                }
                /* 清fat链表结束标志 */
                DEL_FAT_UNIT_END(fc->fp->fat[index1][index2]);
                /* 旧fat单元指向新单元 */
                SET_FAT_UNIT_VALUE(fc->fp->fat[index1][index2], fc->fatWriteIndex);
            }
            /* 在复写数据,移动到下一块 */
            else
            {
                if (tme_fat_chain_writeSeek(fc, fc->writeSeek) != 0) {
                    break;
                }
            }
            /* 新块内存从0开始偏移 */
            fc->writeBlockOffset = 0;
            /* 更新位置 */
            index1 = fc->fatWriteIndex / fc->fp->head->fatUnitNumber;
            index2 = fc->fatWriteIndex % fc->fp->head->fatUnitNumber;
        }
    }
    /* 发生数据写入,则更新文件时长 */
    if (!fc->fp->isReadOnly)
    {
        fc->fp->head->durationMs =
            tme_utils_getTickMs() - fc->fp->beginTickMs + fc->fp->diffTickMs;
    }
    return wCount;
}

int32_t tme_fat_chain_read(TME_FatChain* fc, uint8_t* data, int32_t dataSize)
{
    if (!fc->fp || !fc->readBlock) {
        return -1;
    }
    /* 二维数组位置 */
    int32_t index1 = fc->fatReadIndex / fc->fp->head->fatUnitNumber;
    int32_t index2 = fc->fatReadIndex % fc->fp->head->fatUnitNumber;
    /* 当前fat内存块总的有效数据量 */
    int32_t blockDataSize = GET_FAT_UNIT_END(fc->fp->fat[index1][index2]) ?
        GET_FAT_UNIT_VALUE(fc->fp->fat[index1][index2]) : fc->fp->head->fatUnitBlockSize;
    /* 总的读取数据量 & 局部数据量计数 */
    int32_t rCount = 0;
    int32_t rCountPart = 0;
    while (dataSize > 0)
    {
        /* 当前内存块还有数据可读 */
        if (fc->readBlockOffset < blockDataSize)
        {
            /* 将读取的数据量 */
            rCountPart = blockDataSize - fc->readBlockOffset;
            if (rCountPart > dataSize) {
                rCountPart = dataSize;
            }
            /* 取数据 */
            memcpy(&data[rCount], &fc->readBlock[fc->readBlockOffset], rCountPart);
            /* 计数移动 */
            fc->readSeek += rCountPart;
            fc->readBlockOffset += rCountPart;
            rCount += rCountPart;
            dataSize -= rCountPart;
        }
        /* 当前块已是最后一块 */
        else if (GET_FAT_UNIT_END(fc->fp->fat[index1][index2]))
        {
            break;
        }
        /* 当前块已读取完,转移到下一块 */
        else
        {
            if (tme_fat_chain_readSeek(fc, fc->readSeek) != 0) {
                break;
            }
            /* 新块内存从0开始偏移 */
            fc->readBlockOffset = 0;
            /* 更新位置 */
            index1 = fc->fatReadIndex / fc->fp->head->fatUnitNumber;
            index2 = fc->fatReadIndex % fc->fp->head->fatUnitNumber;
            /* 当前fat内存块总的有效数据量 */
            blockDataSize = GET_FAT_UNIT_END(fc->fp->fat[index1][index2]) ?
                GET_FAT_UNIT_VALUE(fc->fp->fat[index1][index2]) : fc->fp->head->fatUnitBlockSize;
        }
    }
    return rCount;
}

int32_t tme_fat_chain_readSeek(TME_FatChain* fc, int32_t offset)
{
    int32_t blockOffset = 0;
    int32_t fatIndex = _tme_fat_chain_seek(fc->fp, fc->fatBeginIndex, offset, &blockOffset);
    /* 映射文件到 readBlock */
    if (fatIndex >= 0 && (fatIndex != fc->fatReadIndex || !fc->readBlock))
    {
        void* newMem = _tme_mmap_create(
            fc->fp, fc->fp->head->fatUnitBlockSize, _tme_fatIndex2FileAddr(fc->fp->head, fatIndex));
        if (fc->readBlock) {
            tme_mmap_release(fc->readBlock);
        }
        fc->readBlock = (uint8_t*)newMem;
    }
    /* 检查结果&更新参数 */
    if (fatIndex >= 0 && fc->readBlock)
    {
        fc->readSeek = offset < 0 ? fc->totalSize : offset;
        fc->fatReadIndex = fatIndex;
        fc->readBlockOffset = blockOffset;
    }
    return fc->readBlock ? 0 : (-1);
}

int32_t tme_fat_chain_writeSeek(TME_FatChain* fc, int32_t offset)
{
    if (fc->fp->isReadOnly) {
        return -1;
    }
    int32_t blockOffset = 0;
    int32_t fatIndex = _tme_fat_chain_seek(fc->fp, fc->fatBeginIndex, offset, &blockOffset);
    /* 映射文件到 writeBlock */
    if (fatIndex >= 0 && (fatIndex != fc->fatWriteIndex || !fc->writeBlock))
    {
        void* newMem = _tme_mmap_create(
            fc->fp, fc->fp->head->fatUnitBlockSize, _tme_fatIndex2FileAddr(fc->fp->head, fatIndex));
        if (fc->writeBlock) {
            tme_mmap_release(fc->writeBlock);
        }
        fc->writeBlock = (uint8_t*)newMem;
    }
    /* 检查结果&更新参数 */
    if (fatIndex >= 0 && fc->writeBlock)
    {
        fc->writeSeek = offset < 0 ? fc->totalSize : offset;
        fc->fatWriteIndex = fatIndex;
        fc->writeBlockOffset = blockOffset;
    }
    return fc->writeBlock ? 0 : (-1);
}

void* tme_fat_chain_mmap(TME_FatChain* fc, int32_t offset, int32_t memSize)
{
    /* 超出总大小 */
    if (offset + memSize > fc->totalSize) {
        TME_ERR("over limit, offset:%d + memSize:%d > totalSize:%d", offset, memSize, fc->totalSize);
        return NULL;
    }
    /* 超出单元大小 */
    if (memSize > fc->fp->head->fatUnitBlockSize) {
        TME_ERR("size error, %d(memSize) > %d(blockSize)", memSize, fc->fp->head->fatUnitBlockSize);
        return NULL;
    }
    /* 根据offset定位fat单元及其偏移量 */
    int32_t blockOffset = 0;
    int32_t fatIndex = _tme_fat_chain_seek(fc->fp, fc->fatBeginIndex, offset, &blockOffset);
    /* 出现跨区 */
    if ((blockOffset % fc->fp->head->fatUnitBlockSize) + memSize > fc->fp->head->fatUnitBlockSize) {
        TME_ERR("cross block, offset:%d + memSize:%d > blockSize:%d",
            (blockOffset % fc->fp->head->fatUnitBlockSize), memSize, fc->fp->head->fatUnitBlockSize);
        return NULL;
    }
    /* 定位实际文件地址 */
    int32_t addr = _tme_fatIndex2FileAddr(fc->fp->head, fatIndex) + blockOffset;
    /* 映射内存 */
    return tme_mmap_create(fc->fp->fp, memSize, addr, fc->fp->isReadOnly);
}

int32_t tme_fat_chain_unmmap(void* mem)
{
    tme_mmap_release(mem);
    return 0;
}
